package com.ecut.xzh.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.StrUtil;
import com.ecut.xzh.constant.MessageConstant;
import com.ecut.xzh.constant.RedisConstant;
import com.ecut.xzh.context.UserHolder;
import com.ecut.xzh.dto.ArticleDTO;
import com.ecut.xzh.dto.ArticlePageDTO;
import com.ecut.xzh.entity.Article;
import com.ecut.xzh.entity.User;
import com.ecut.xzh.exception.*;
import com.ecut.xzh.mapper.ArticleMapper;
import com.ecut.xzh.mapper.UserMapper;
import com.ecut.xzh.result.PageResult;
import com.ecut.xzh.service.ArticleService;
import com.ecut.xzh.vo.ArticleDetailVO;
import com.ecut.xzh.vo.ArticleVO;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author XZH
 */
@Service
public class ArticleServiceImpl implements ArticleService {

    @Resource
    private ArticleMapper articleMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 新增文章
     * @param articleDTO
     */
    @Override
    public void addArticle(ArticleDTO articleDTO) {
        // 文章标题或内容为空
        if (StrUtil.isBlank(articleDTO.getTitle())) {
            throw new TitleOrContentIsNullException(MessageConstant.TITLE_OR_CONTENT_IS_NULL);
        }

        // 复制属性
        Article article = new Article();
        BeanUtil.copyProperties(articleDTO, article);

        // 设置创建时间和更新时间为当前时间
        article.setCreateTime(LocalDateTime.now());
        article.setUpdateTime(LocalDateTime.now());

        Long studentId = UserHolder.getCurrentId();
        article.setStudentId(studentId);

        articleMapper.insert(article);
    }

    /**
     * 文章分页查询
     *
     * @param articlePageDTO
     * @return
     */
    @Override
    public PageResult pageArticle(ArticlePageDTO articlePageDTO) {
        PageHelper.startPage(articlePageDTO.getPageNum(), articlePageDTO.getPageSize());
        Page<ArticleVO> page = articleMapper.pageArticle(articlePageDTO);

        List<ArticleVO> records = page.getResult();
        // 判断当前用户是否点赞
        records.forEach(articleVO -> {
            // 如果已经点赞，值为true并设置未true
            articleVO.setIsLike(BooleanUtil.isTrue(this.isArticleLiked(articleVO.getId())));
        });

        return new PageResult(page.getTotal(), records);
    }

    /**
     * 获取文章详细信息
     *
     * @param id
     * @return
     */
    @Override
    public ArticleDetailVO getArticleById(Long id) {
        ArticleDetailVO articleDetailVO = articleMapper.getById(id);
        if(articleDetailVO == null){
            throw new ArticleNotFoundException(MessageConstant.ARTICLE_NOT_FIND);
        }
        // 如果已经点赞，值为true并设置未true
        articleDetailVO.setIsLike(BooleanUtil.isTrue(isArticleLiked(id)));
        return articleDetailVO;
    }

    /**
     *  判断当前用户是否已经点赞
     * @param id
     * @return
     */
    private Boolean isArticleLiked(Long id){
        // 获取当前用户
        Long userId = UserHolder.getCurrentId();

        // 判断当前用户是否已经点赞
        String key = RedisConstant.ARTICLE_LIKED + id;
        return stringRedisTemplate.opsForSet().isMember(key, userId.toString());
    }

    /**
     * 点赞文章
     * @param id
     */
    @Override
    public void likeArticle(Long id) {
        // 获取当前用户
        Long userId = UserHolder.getCurrentId();

        // 判断当前用户是否已经点赞
        String key = RedisConstant.ARTICLE_LIKED + id;
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, userId.toString());
        if(BooleanUtil.isFalse(isMember)){
            // 如果未点赞，可以点赞
            // 数据库点赞数 + 1
            Boolean isSuccess = articleMapper.plusOneById(id);
            // 保存用户到redis的set集合中
            if(isSuccess){
                stringRedisTemplate.opsForSet().add(key, userId.toString());
            }
        } else {
            // 如果已经点赞，取消点赞
            // 数据库点赞数 - 1
            Boolean isSuccess = articleMapper.reduceOneById(id);
            // 把用户从redis的set集合中移除
            if(isSuccess){
                stringRedisTemplate.opsForSet().remove(key, userId.toString());
            }
        }
    }
}
